package com.blog.cmrpersonalblog.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blog.cmrpersonalblog.dto.announcement.request.*;
import com.blog.cmrpersonalblog.dto.announcement.response.AnnouncementResponse;
import com.blog.cmrpersonalblog.dto.announcement.response.UserAnnouncementMessageResponse;
import com.blog.cmrpersonalblog.entity.Announcement;
import com.blog.cmrpersonalblog.entity.UserAnnouncementRead;
import com.blog.cmrpersonalblog.enums.ActivityType;
import com.blog.cmrpersonalblog.mapper.AnnouncementMapper;
import com.blog.cmrpersonalblog.mapper.UserAnnouncementReadMapper;
import com.blog.cmrpersonalblog.service.AnnouncementService;
import com.blog.cmrpersonalblog.service.UserActivityService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 公告服务实现类
 */
@Slf4j
@Service
public class AnnouncementServiceImpl extends ServiceImpl<AnnouncementMapper, Announcement> implements AnnouncementService {

   @Resource
    private AnnouncementMapper announcementMapper;

   @Resource
    private UserAnnouncementReadMapper userAnnouncementReadMapper;

   @Resource
    private UserActivityService userActivityService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createAnnouncement(AnnouncementCreateRequest createRequest, Long creatorId, String creatorName) {
        try {
            Announcement announcement = new Announcement();
            BeanUtils.copyProperties(createRequest, announcement);
            
            // 设置创建人信息
            announcement.setCreatorId(creatorId);
            announcement.setCreatorName(creatorName);
            
            // 如果状态为已发布且没有设置发布时间，则使用当前时间
            if (announcement.getStatus() == 1 && announcement.getPublishTime() == null) {
                announcement.setPublishTime(LocalDateTime.now());
            }
            
            // 初始化查看次数
            announcement.setViewCount(0);
            
            boolean success = save(announcement);
            
            if (success) {
                // 记录活动
                userActivityService.recordActivity(
                    creatorId,
                    ActivityType.ANNOUNCEMENT_CREATE,
                    "创建公告: " + announcement.getTitle(),
                    announcement.getId(),
                    "announcement",
                    null,
                    null,
                    "SUCCESS",
                    null
                );
                
                log.info("公告创建成功: id={}, title={}, creator={}", 
                    announcement.getId(), announcement.getTitle(), creatorName);
            }
            
            return success;
        } catch (Exception e) {
            log.error("创建公告失败", e);
            throw new RuntimeException("创建公告失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAnnouncement(AnnouncementUpdateRequest updateRequest) {
        try {
            Announcement existingAnnouncement = getById(updateRequest.getId());
            if (existingAnnouncement == null) {
                throw new RuntimeException("公告不存在");
            }
            
            // 检查是否可以修改
            if (existingAnnouncement.getStatus() == 3) {
                throw new RuntimeException("已删除的公告不能修改");
            }
            
            Announcement announcement = new Announcement();
            BeanUtils.copyProperties(updateRequest, announcement);
            
            // 如果状态改为已发布且原来不是已发布状态，设置发布时间
            if (announcement.getStatus() != null && announcement.getStatus() == 1 
                && existingAnnouncement.getStatus() != 1 && announcement.getPublishTime() == null) {
                announcement.setPublishTime(LocalDateTime.now());
            }
            
            boolean success = updateById(announcement);
            
            if (success) {
                // 记录活动
                userActivityService.recordActivity(
                    updateRequest.getUpdaterId(),
                    ActivityType.ANNOUNCEMENT_UPDATE,
                    "更新公告: " + (updateRequest.getTitle() != null ? updateRequest.getTitle() : existingAnnouncement.getTitle()),
                    updateRequest.getId(),
                    "announcement",
                    null,
                    null,
                    "SUCCESS",
                    null
                );
                
                log.info("公告更新成功: id={}, updater={}", 
                    updateRequest.getId(), updateRequest.getUpdaterName());
            }
            
            return success;
        } catch (Exception e) {
            log.error("更新公告失败", e);
            throw new RuntimeException("更新公告失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAnnouncement(Long announcementId, Long operatorId, String operatorName) {
        try {
            Announcement announcement = getById(announcementId);
            if (announcement == null) {
                throw new RuntimeException("公告不存在");
            }
            
            // 逻辑删除：设置状态为已删除
            announcement.setStatus(3);
            announcement.setUpdaterId(operatorId);
            announcement.setUpdaterName(operatorName);
            
            boolean success = updateById(announcement);
            
            if (success) {
                // 记录活动
                userActivityService.recordActivity(
                    operatorId,
                    ActivityType.ANNOUNCEMENT_DELETE,
                    "删除公告: " + announcement.getTitle(),
                    announcementId,
                    "announcement",
                    null,
                    null,
                    "SUCCESS",
                    null
                );
                
                log.info("公告删除成功: id={}, title={}, operator={}", 
                    announcementId, announcement.getTitle(), operatorName);
            }
            
            return success;
        } catch (Exception e) {
            log.error("删除公告失败", e);
            throw new RuntimeException("删除公告失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchOperateAnnouncements(AnnouncementBatchOperationRequest batchRequest) {
        Map<String, Object> result = new HashMap<>();
        int successCount = 0;
        int failCount = 0;
        List<String> errors = new ArrayList<>();
        
        try {
            for (Long announcementId : batchRequest.getAnnouncementIds()) {
                try {
                    boolean success = false;
                    
                    switch (batchRequest.getOperation()) {
                        case "publish":
                            success = publishAnnouncement(announcementId, batchRequest.getOperatorId(), batchRequest.getOperatorName());
                            break;
                        case "archive":
                            success = archiveAnnouncement(announcementId, batchRequest.getOperatorId(), batchRequest.getOperatorName());
                            break;
                        case "delete":
                            success = deleteAnnouncement(announcementId, batchRequest.getOperatorId(), batchRequest.getOperatorName());
                            break;
                        case "top":
                            success = toggleAnnouncementTop(announcementId, true, batchRequest.getOperatorId(), batchRequest.getOperatorName());
                            break;
                        case "untop":
                            success = toggleAnnouncementTop(announcementId, false, batchRequest.getOperatorId(), batchRequest.getOperatorName());
                            break;
                        case "popup":
                            success = toggleAnnouncementPopup(announcementId, true, batchRequest.getOperatorId(), batchRequest.getOperatorName());
                            break;
                        case "unpopup":
                            success = toggleAnnouncementPopup(announcementId, false, batchRequest.getOperatorId(), batchRequest.getOperatorName());
                            break;
                        default:
                            errors.add("公告ID " + announcementId + ": 不支持的操作类型");
                            failCount++;
                            continue;
                    }
                    
                    if (success) {
                        successCount++;
                    } else {
                        failCount++;
                        errors.add("公告ID " + announcementId + ": 操作失败");
                    }
                } catch (Exception e) {
                    failCount++;
                    errors.add("公告ID " + announcementId + ": " + e.getMessage());
                    log.error("批量操作公告失败: id={}, operation={}", announcementId, batchRequest.getOperation(), e);
                }
            }
            
            result.put("successCount", successCount);
            result.put("failCount", failCount);
            result.put("errors", errors);
            result.put("totalCount", batchRequest.getAnnouncementIds().size());
            
            log.info("批量操作公告完成: operation={}, total={}, success={}, fail={}", 
                batchRequest.getOperation(), batchRequest.getAnnouncementIds().size(), successCount, failCount);
            
        } catch (Exception e) {
            log.error("批量操作公告异常", e);
            throw new RuntimeException("批量操作失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public IPage<AnnouncementResponse> getAnnouncementList(AnnouncementQueryRequest queryRequest) {
        try {
            Page<AnnouncementResponse> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
            return announcementMapper.selectAnnouncementPage(page, queryRequest);
        } catch (Exception e) {
            log.error("查询公告列表失败", e);
            throw new RuntimeException("查询公告列表失败: " + e.getMessage());
        }
    }

    @Override
    public IPage<AnnouncementResponse> getValidAnnouncementList(AnnouncementQueryRequest queryRequest, Long userId) {
        try {
            Page<AnnouncementResponse> page = new Page<>(queryRequest.getCurrent(), queryRequest.getSize());
            return announcementMapper.selectValidAnnouncementPage(page, queryRequest, userId);
        } catch (Exception e) {
            log.error("查询有效公告列表失败", e);
            throw new RuntimeException("查询有效公告列表失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AnnouncementResponse getAnnouncementDetail(Long announcementId, Long userId) {
        try {
            AnnouncementResponse response = announcementMapper.selectAnnouncementDetail(announcementId, userId);
            if (response == null) {
                throw new RuntimeException("公告不存在");
            }
            
            // 增加查看次数
            announcementMapper.incrementViewCount(announcementId);
            
            // 如果是用户查看且未读，标记为已读
            if (userId != null && (response.getRead() == null || !response.getRead())) {
                markAnnouncementAsRead(announcementId, userId);
                response.setRead(true);
            }
            
            return response;
        } catch (Exception e) {
            log.error("获取公告详情失败", e);
            throw new RuntimeException("获取公告详情失败: " + e.getMessage());
        }
    }

    @Override
    public List<AnnouncementResponse> getTopAnnouncements(String targetAudience, Long userId) {
        try {
            return announcementMapper.selectTopAnnouncements(targetAudience, userId);
        } catch (Exception e) {
            log.error("获取置顶公告失败", e);
            throw new RuntimeException("获取置顶公告失败: " + e.getMessage());
        }
    }

    @Override
    public List<AnnouncementResponse> getPopupAnnouncements(String targetAudience, Long userId) {
        try {
            return announcementMapper.selectPopupAnnouncements(targetAudience, userId);
        } catch (Exception e) {
            log.error("获取弹窗公告失败", e);
            throw new RuntimeException("获取弹窗公告失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAnnouncementAsRead(Long announcementId, Long userId) {
        try {
            UserAnnouncementRead readRecord = new UserAnnouncementRead();
            readRecord.setUserId(userId);
            readRecord.setAnnouncementId(announcementId);
            readRecord.setReadStatus(1); // 1-已读
            readRecord.setReadTime(LocalDateTime.now());

            return userAnnouncementReadMapper.insert(readRecord) > 0;
        } catch (Exception e) {
            // 如果是重复插入（已读），忽略错误
            log.debug("标记公告已读失败（可能已读）: announcementId={}, userId={}", announcementId, userId);
            return true;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAllAnnouncementsAsRead(Long userId, String targetAudience) {
        try {
            int count = userAnnouncementReadMapper.markAllAsRead(userId, targetAudience);
            log.info("标记所有公告已读: userId={}, targetAudience={}, count={}", userId, targetAudience, count);
            return true;
        } catch (Exception e) {
            log.error("标记所有公告已读失败", e);
            throw new RuntimeException("标记所有公告已读失败: " + e.getMessage());
        }
    }

    @Override
    public int getUnreadAnnouncementCount(Long userId, String targetAudience) {
        try {
            return userAnnouncementReadMapper.countUnreadAnnouncements(userId, targetAudience);
        } catch (Exception e) {
            log.error("获取未读公告数量失败", e);
            return 0;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publishAnnouncement(Long announcementId, Long operatorId, String operatorName) {
        try {
            Announcement announcement = getById(announcementId);
            if (announcement == null) {
                throw new RuntimeException("公告不存在");
            }

            if (announcement.getStatus() == 3) {
                throw new RuntimeException("已删除的公告不能发布");
            }

            announcement.setStatus(1);
            announcement.setUpdaterId(operatorId);
            announcement.setUpdaterName(operatorName);

            // 如果没有发布时间，设置为当前时间
            if (announcement.getPublishTime() == null) {
                announcement.setPublishTime(LocalDateTime.now());
            }

            boolean success = updateById(announcement);

            if (success) {
                // 记录活动
                userActivityService.recordActivity(
                    operatorId,
                    ActivityType.ANNOUNCEMENT_PUBLISH,
                    "发布公告: " + announcement.getTitle(),
                    announcementId,
                    "announcement",
                    null,
                    null,
                    "SUCCESS",
                    null
                );

                log.info("公告发布成功: id={}, title={}, operator={}",
                    announcementId, announcement.getTitle(), operatorName);
            }

            return success;
        } catch (Exception e) {
            log.error("发布公告失败", e);
            throw new RuntimeException("发布公告失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean archiveAnnouncement(Long announcementId, Long operatorId, String operatorName) {
        try {
            Announcement announcement = getById(announcementId);
            if (announcement == null) {
                throw new RuntimeException("公告不存在");
            }

            announcement.setStatus(2); // 设为已过期
            announcement.setUpdaterId(operatorId);
            announcement.setUpdaterName(operatorName);

            boolean success = updateById(announcement);

            if (success) {
                // 记录活动
                userActivityService.recordActivity(
                    operatorId,
                    ActivityType.ANNOUNCEMENT_ARCHIVE,
                    "存档公告: " + announcement.getTitle(),
                    announcementId,
                    "announcement",
                    null,
                    null,
                    "SUCCESS",
                    null
                );

                log.info("公告存档成功: id={}, title={}, operator={}",
                    announcementId, announcement.getTitle(), operatorName);
            }

            return success;
        } catch (Exception e) {
            log.error("存档公告失败", e);
            throw new RuntimeException("存档公告失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean toggleAnnouncementTop(Long announcementId, boolean isTop, Long operatorId, String operatorName) {
        try {
            Announcement announcement = getById(announcementId);
            if (announcement == null) {
                throw new RuntimeException("公告不存在");
            }

            announcement.setIsTop(isTop ? 1 : 0);
            announcement.setUpdaterId(operatorId);
            announcement.setUpdaterName(operatorName);

            boolean success = updateById(announcement);

            if (success) {
                String operation = isTop ? "置顶" : "取消置顶";
                log.info("公告{}成功: id={}, title={}, operator={}",
                    operation, announcementId, announcement.getTitle(), operatorName);
            }

            return success;
        } catch (Exception e) {
            log.error("切换公告置顶状态失败", e);
            throw new RuntimeException("切换公告置顶状态失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean toggleAnnouncementPopup(Long announcementId, boolean isPopup, Long operatorId, String operatorName) {
        try {
            Announcement announcement = getById(announcementId);
            if (announcement == null) {
                throw new RuntimeException("公告不存在");
            }

            announcement.setIsPopup(isPopup ? 1 : 0);
            announcement.setUpdaterId(operatorId);
            announcement.setUpdaterName(operatorName);

            boolean success = updateById(announcement);

            if (success) {
                String operation = isPopup ? "设为弹窗" : "取消弹窗";
                log.info("公告{}成功: id={}, title={}, operator={}",
                    operation, announcementId, announcement.getTitle(), operatorName);
            }

            return success;
        } catch (Exception e) {
            log.error("切换公告弹窗状态失败", e);
            throw new RuntimeException("切换公告弹窗状态失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int autoExpireAnnouncements() {
        try {
            int count = announcementMapper.autoExpireAnnouncements();
            if (count > 0) {
                log.info("自动过期公告: count={}", count);
            }
            return count;
        } catch (Exception e) {
            log.error("自动过期公告失败", e);
            return 0;
        }
    }

    @Override
    public Map<String, Object> getAnnouncementStatistics() {
        try {
            return announcementMapper.selectAnnouncementStatistics();
        } catch (Exception e) {
            log.error("获取公告统计信息失败", e);
            return new HashMap<>();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cleanDeletedAnnouncements(int daysBeforeClean) {
        try {
            LocalDateTime beforeTime = LocalDateTime.now().minusDays(daysBeforeClean);
            int count = announcementMapper.cleanDeletedAnnouncements(beforeTime);
            if (count > 0) {
                log.info("清理已删除公告: count={}, beforeTime={}", count, beforeTime);
            }
            return count;
        } catch (Exception e) {
            log.error("清理已删除公告失败", e);
            return 0;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int cleanExpiredReadRecords(int daysBeforeClean) {
        try {
            LocalDateTime beforeTime = LocalDateTime.now().minusDays(daysBeforeClean);
            int count = userAnnouncementReadMapper.cleanExpiredReadRecords(beforeTime);
            if (count > 0) {
                log.info("清理过期阅读记录: count={}, beforeTime={}", count, beforeTime);
            }
            return count;
        } catch (Exception e) {
            log.error("清理过期阅读记录失败", e);
            return 0;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean ignoreAnnouncement(Long announcementId, Long userId) {
        try {
            // 验证公告是否存在
            Announcement announcement = getById(announcementId);
            if (announcement == null) {
                throw new RuntimeException("公告不存在");
            }

            // 标记为已忽略
            int count = userAnnouncementReadMapper.markAsIgnored(userId, announcementId);

            if (count > 0) {
                log.info("用户忽略公告成功: userId={}, announcementId={}", userId, announcementId);
                return true;
            }

            return false;
        } catch (Exception e) {
            log.error("忽略公告失败", e);
            throw new RuntimeException("忽略公告失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelIgnoreAnnouncement(Long announcementId, Long userId) {
        try {
            // 取消忽略（删除忽略记录）
            int count = userAnnouncementReadMapper.cancelIgnore(userId, announcementId);

            if (count > 0) {
                log.info("用户取消忽略公告成功: userId={}, announcementId={}", userId, announcementId);
                return true;
            }

            return false;
        } catch (Exception e) {
            log.error("取消忽略公告失败", e);
            throw new RuntimeException("取消忽略公告失败: " + e.getMessage());
        }
    }

    @Override
    public IPage<UserAnnouncementMessageResponse> getUserMessageAnnouncementList(
            UserAnnouncementMessageQueryRequest queryRequest,
            Long userId,
            String targetAudience) {
        try {
            Page<UserAnnouncementMessageResponse> page =
                new Page<>(queryRequest.getSafeCurrent(), queryRequest.getSafeSize());

            IPage<UserAnnouncementMessageResponse> pageResult =
                announcementMapper.selectUserMessageAnnouncementPage(page, queryRequest, userId, targetAudience);

            // 设置类型名称、级别名称、阅读状态名称
            pageResult.getRecords().forEach(response -> {
                response.setTypeName();
                response.setLevelName();
                response.setReadStatusName();
            });

            return pageResult;
        } catch (Exception e) {
            log.error("获取用户消息中心公告列表失败", e);
            throw new RuntimeException("获取用户消息中心公告列表失败: " + e.getMessage());
        }
    }
}
